iT邦幫忙

2021 iThome 鐵人賽

DAY 7
1
自我挑戰組

資料分析及AI深度學習-簡單基礎實作系列 第 7

DAY7:Kaggle-San Francisco Crime Classification(下)

  • 分享至 

  • xImage
  •  
  • 資料視覺化

這邊我們會用到seaborn來做一下簡單的資料視覺化。

import seaborn as sns

sns.set()

我們先來看看犯罪類型的數量,由於種類較多,我就先截部分。

data = train.groupby('Category').count()
data = data['Dates'].sort_values(ascending=False)
print(data)

接下來我們將它視覺化,這樣就可以很清楚的看到各種犯罪類型的佔比。

plt.figure(figsize=(20, 12))
ax = sns.barplot((data.values / data.values.sum())*100,data.index)
plt.title('Count by Category', fontdict={'fontsize': 21})
plt.xlabel('Percentage')

再來看看在幾點鐘的時候比較有犯罪發生,類型是甚麼呢?

fig, ax = plt.subplots(figsize=(24,16))
fig.suptitle('Num. Incidents / Hour (Category)')
for category in train['Category'].unique():
    #print(category)
    data = train[train['Category'] == category].groupby('Hour')
    a = data['Hour'].count()
    ax.plot(a.index, data['Hour'].count(), label=category)
plt.legend()
plt.show()

可以很清楚看到在傍晚約18-19點犯罪是最多的。

再來我們看看星期幾跟犯罪的相關性。

fig, ax = plt.subplots(figsize=(24,16))

def plotbycol(df, col, title):
    fig.suptitle(title)
    for category in df['Category'].unique():
        #print(category)
        data = df[df['Category'] == category].groupby(col)
        a = data[col].count()
        ax.plot(a.index, data[col].count(), label=category)
    
    plt.legend()
    plt.show()
    
plotbycol(train, 'DayOfWeek', "Incidents by Week")

這看起來沒有說星期幾特別容易有犯罪。


  • 資料前處理

接續昨天的資料前處理,今天還有一部分的資料處理沒做完,我們要先將類別變數變成虛擬變數之後,才能丟進模型建模。

變成虛擬變數的常見方法有兩種:
  1. One hot encoding:把要處理的特徵(假設此特徵有N個類別),新增成N欄,每欄只會有兩個數值,0或1,由0為非,1為是,來表示原本的特徵是屬於哪個類別。
  2. label encoding:把要處理的特徵(假設此特徵有N個類別),把其中的類別轉換成0~(N-1)的數字,分別去代表其中的類別。

這裡我們用到One hot encoding,我們先將我們要預測的應變數Y拉出來。

y=pd.get_dummies(train['Category'])
print(y.head(5))

如下圖,可以看見一欄被分成39欄,分別用0或1代表是否屬於那個類別。

在train和test部分,我們還有兩個變數要做轉換,"PdDistrict"以及"Block",另外我們把特徵"Year"也刪除,test的"Id"也要刪除。

# 處理"PdDistrict"
dummies_train=pd.get_dummies(train['PdDistrict'])
dummies_test=pd.get_dummies(test['PdDistrict'])

# 將原本的"PdDistrict"特徵刪除
train=pd.concat([train,dummies_train],axis=1)
train.drop('PdDistrict',inplace=True,axis=1)

test=pd.concat([test,dummies_test],axis=1)
test.drop('PdDistrict',inplace=True,axis=1)

# 處理"Block"
dummies_train=pd.get_dummies(train['Block'])
dummies_test=pd.get_dummies(test['Block'])

# 將原本的"Block"特徵刪除
train=pd.concat([train,dummies_train],axis=1)
train.drop('Block',inplace=True,axis=1)

test=pd.concat([test,dummies_test],axis=1)
test.drop('Block',inplace=True,axis=1)

# 另外這邊想把Year這個變數也刪除掉,跟刪除日期的理由一樣
X=train.drop(['Category','Year'],axis=1)
test.drop('Year',inplace=True,axis=1)

# test的Id也是,先將他刪除
test_no_id = test.drop('Id',axis=1)

print("X資料集")
print(X.head(5))
print("=====================================================================================")
print("test資料集")
print(test_no_id.head(5))

這是我們處理完,X資料集是我們要丟入模型訓練的資料,test則是模型訓練出來,要丟進去預測的資料。

再來我們用tensorflow架一個神經網路當作我們的模型。

from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=42)
print(X_train.shape,y_train.shape)
print(X_test.shape,y_test.shape)

這邊我們一個神經網路模型,隱藏層的激活函數都用relu,輸出層我們用softmax。另外我們要給model一個優化器,這邊我選擇用adam,它收斂較快,loss_function選擇crossentropy。

from tensorflow import keras
from keras.layers import Dense,Dropout
from keras.models import Sequential

model=Sequential()
model.add(Dense(128,input_shape=(X.shape[1],)))
model.add(Dense(128,activation='relu'))
model.add(Dense(128,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(64,activation='relu'))
model.add(Dense(39,activation='softmax'))
model.summary()

model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])        
train=model.fit(X_train,y_train, 
         batch_size=512,
         epochs=100,
         verbose=2,
         validation_data=(X_test,y_test))      

接下來就丟進去模型訓練啦!!

train=model.fit(X_train,y_train, batch_size=512,epochs=100,verbose=2,validation_data=(X_test,y_test))

恩...準確度好像是滿糟糕的,但多分類,覺得先上傳試試看,先能做出來,再來調整修改!

拿練好的模型來預測囉!!

pred=model.predict(test_no_id)

m = np.max(pred, axis=1).reshape(-1, 1)
predicted = np.array((pred == m), dtype='int64')
print(predicted)

這是我產出的樣子,總共有39個類別,屬於那個類別就為1,否則為0。

然後就產出CSV上傳啦

sample=pd.read_csv(r'C:\Users\Frank\Desktop\kaggledata\sf-crime\sampleSubmission.csv')
col_names=list(sample.columns)
col_names.remove('Id')
submission = pd.DataFrame()
submission['Id']=test['Id']
for i, entry in enumerate(col_names):
    submission[entry] = predicted[:,i]

submission.to_csv(r'./submission_crime.csv', index=False)

這個分數是越低越好,它是用loss去評分的,不過對我們來說分數不重要,重點是你練習會了整個流程,從拿到資料,資料前處理,再到產出模型,產出你的預測。會了之後再回頭看哪邊可以調整試試看,讓分數變得更好看。

  • 今日小結

這是我們碰到第一個多分類的問題,其實流程來說都差不多,那多分類的模型就要選擇一下,例如羅吉斯回歸就不是用在多分類,Adaboost、SVC也是,模型的部分就可以選擇一下,我也有試著用集成學習來跑,但因為跑太久,還沒出來,等出來結果如果有比較好再來跟大家分享囉!!
明天要來試著玩看看圖像辨識的部分,因為工作有用到驗證碼辨識,我就把它紀錄下來,當作我的學習記錄囉~


上一篇
DAY6:Kaggle-San Francisco Crime Classification(上)
下一篇
DAY8:驗證碼辨識(一)
系列文
資料分析及AI深度學習-簡單基礎實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言